package com.joymart.order.rest;


import com.joymart.common.model.Range;
import com.joymart.common.utils.DatetimeUtils;
import com.joymart.common.utils.ExcelExporter;
import com.joymart.common.utils.SecurityUtils;
import com.joymart.order.model.Order;
import com.joymart.order.service.OrderFlowService;
import com.joymart.order.service.OrderQueryService;
import com.joymart.order.service.OrderService;
import com.joymart.recipient.model.Recipient;
import com.joymart.recipient.service.RecipientService;
import lombok.Data;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

@RestController
public class OrderController {

    @Autowired
    private OrderQueryService orderQueryService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private RecipientService recipientService;
    @Autowired
    private OrderFlowService orderFlowService;




    @GetMapping("/customer/orders")
    public Page<OrderQueryService.OrderDTO> searchOrders(LocalDateTime start, LocalDateTime end,
                                                         @RequestParam(value = "pageNo", defaultValue = "0")Integer pageNo,
                                                         @RequestParam(value = "pageSize", defaultValue = "20")Integer pageSize,
                                                         @RequestParam(value = "receiver", required = false)String receiver,
                                                         @RequestParam(value = "orderId", required = false) String orderId,
                                                         @RequestParam(value = "category", defaultValue = "") String category) {

        Range range = Range.of(start, end);
        DatetimeUtils.checkRangeWithin(90,range);


        if(!StringUtils.hasText(category)){
            //所有订单
            return  orderQueryService.searchCustomerOrders(range, receiver, orderId, PageRequest.of(pageNo,pageSize));
        }else if(category.equals (Order.Status.BUYER_PAID.name())){
            //对于顾客来说，无论是等待 管理店铺/经营店铺/总部 都是待发货状态
            return orderQueryService.searchCustomerOrders(range, receiver, orderId, PageRequest.of(pageNo,pageSize),
                    Order.Status.BUYER_PAID,
                    Order.Status.FIRST_SELLER_PAID,
                    Order.Status.SECOND_SELLER_PAID);
        }else {
            return orderQueryService.searchCustomerOrders(range, receiver, orderId, PageRequest.of(pageNo, pageSize),
                    Order.Status.valueOf(category));
        }

    }

    @GetMapping("/customer/orders/export")
    public ResponseEntity<byte[]> exportOrders(LocalDateTime start, LocalDateTime end,
                                               @RequestParam(value = "receiver", required = false)String receiver,
                                               @RequestParam(value = "orderId", required = false) String orderId,
                                               @RequestParam(value = "category", defaultValue = "") String category){
        List<OrderQueryService.OrderDTO> dtos = this.searchOrders(start,end,0,100000,receiver,orderId,category).getContent();
        return this.downloadOrderExcel(dtos, Range.of(start,end));

    }


    /**
     * @param start
     * @param end
     * @param category //NEED_CONFIRMATION 待确认 / CONFIRMED 已确认，待上级操作 / SECOND_SELLER_PAID 待发货 /DELIVERING 已发货，运输中 / RECEIVED 收货，订单完成
     * @param receiver
     * @return
     */
    @GetMapping("/shop/orders")
    public Page<OrderQueryService.OrderDTO> searchShopOrders(
                                                             @RequestParam LocalDateTime start,
                                                             @RequestParam LocalDateTime end,
                                                             @RequestParam(value = "category", defaultValue = "")String category,
                                                             @RequestParam(value = "pageNo", defaultValue = "0")Integer pageNo,
                                                             @RequestParam(value = "pageSize", defaultValue = "20")Integer pageSize,
                                                             @RequestParam(value = "receiver", required = false)String receiver,
                                                             @RequestParam(value = "orderId", required = false) String orderId) {

        Range range = Range.of(start, end);
        DatetimeUtils.checkRangeWithin(90,range);


        return orderQueryService.searchShopOrders(
                range,
                orderId,
                category,
                receiver,
                PageRequest.of(pageNo, pageSize));
    }

    @GetMapping("/shop/orders/export")
    public ResponseEntity<byte[]> exportShopOrders(
            @RequestParam LocalDateTime start,
            @RequestParam LocalDateTime end,
            @RequestParam(value = "category", defaultValue = "")String category,
            @RequestParam(value = "receiver", required = false)String receiver,
            @RequestParam(value = "orderId", required = false) String orderId) {

        List<OrderQueryService.OrderDTO> dtos = this.searchShopOrders(start,end,category,0,100000,receiver,orderId).getContent();
        return this.downloadOrderExcel(dtos, Range.of(start,end));
    }


    /**
     * 买家下单
     * @param param
     * @return
     */
    @PostMapping("/orders")
    public OrderQueryService.OrderDTO makeOrder(@RequestBody MakeOrderParam param) {
        Order order = new Order();
        order.setProductId(param.getProductId());
        order.setQuantity(param.getQuantity());
        order.setRemark(param.getRemark());
        Recipient recipient = recipientService.findById(param.getRecipientId());
        SecurityUtils.checkCurrentUserIsAny(recipient::getUserId);
        order.setReceiverAddress(recipient.getAddress());
        order.setReceiverPhone(recipient.getPhone());
        order.setReceiverName(recipient.getContact());
        order.setReceiverDistrict(recipient.getDistrict());
        orderFlowService.makeOrder(order);

        return orderQueryService.findById(order.getId());
    }

    /**
     * 订单详情
     * @param orderId
     * @return
     */
    @GetMapping(value = "/orders/{id}")
    public OrderQueryService.OrderDTO detail(@PathVariable("id") String orderId) {
        return orderQueryService.findById(orderId);
    }

    /**
     * 管理店铺确认经营店铺付款付款
     * @param orderId
     * @return
     */
    @PutMapping(value = "/orders/{id}", params = "action=CONFIRM_FIRST_SELLER_PAID")
    public OrderQueryService.OrderDTO confirmFirstSellerPaid(@PathVariable("id") String orderId) {
        Order order = orderService.getById(orderId);
        orderFlowService.confirmFirstSellerPaid(order);
        return orderQueryService.findById(orderId);
    }

    /**
     * 买家提醒经营店铺确认收款
     * @param orderId
     * @return
     */
    @PutMapping(value = "/orders/{id}", params = "action=INFORM_FIRST_SELLER")
    public OrderQueryService.OrderDTO informFirstSeller(@PathVariable("id") String orderId) {
        Order order = orderService.getById(orderId);
        orderFlowService.informFirstSeller(order);
        return orderQueryService.findById(orderId);
    }

    /**
     * 经营店铺提醒管理店铺确认收款
     * @param orderId
     * @return
     */
    @PutMapping(value = "/orders/{id}", params = "action=INFORM_SECOND_SELLER")
    public OrderQueryService.OrderDTO informSecondSeller(@PathVariable("id") String orderId) {
        Order order = orderService.getById(orderId);
        orderFlowService.informSecondSeller(order);
        return orderQueryService.findById(orderId);
    }

    /**
     * 经营店铺确认买家付款
     * @param orderId
     * @return
     */
    @PutMapping(value = "/orders/{id}", params = "action=CONFIRM_BUYER_PAID")
    public OrderQueryService.OrderDTO confirmBuyerPaid(@PathVariable("id") String orderId) {
        Order order = orderService.getById(orderId);
        orderFlowService.confirmBuyerPaid(order);
        return orderQueryService.findById(orderId);
    }
    /**
     * 买家取消订单
     * @param orderId
     * @return
     */
    @PutMapping(value = "/orders/{id}", params = "action=CANCEL")
    public OrderQueryService.OrderDTO cancelOrder(@PathVariable("id") String orderId) {
        Order order = orderService.getById(orderId);
        orderFlowService.manualCancel(order);
        return orderQueryService.findById(orderId);
    }

    /**
     * 买家确认收货
     * @param orderId
     * @return
     */
    @PutMapping(value = "/orders/{id}", params = "action=RECEIVE")
    public OrderQueryService.OrderDTO receive(@PathVariable("id") String orderId) {
        Order order = orderService.getById(orderId);
        orderFlowService.receive(order);
        return orderQueryService.findById(orderId);
    }


    @SneakyThrows
    private ResponseEntity<byte[]> downloadOrderExcel(List<OrderQueryService.OrderDTO> dtos, Range range) {

        ExcelExporter<OrderQueryService.OrderDTO> orderDTOExcelExporter = new ExcelExporter<>() {
            @Override
            protected String getSheetName() {
                return "历史订单";
            }

            @Override
            protected List<String> getHeaders() {
                return List.of("单号","品名","数量","单价","总价","店铺", "买家","创建时间","状态","收货人姓名","收货人地址","收货人电话","快递单号");
            }

        };

        Function<OrderQueryService.OrderDTO, List<Object>> rowMapper  = dto->Arrays.asList(
            dto.getId(), dto.getProductName(), dto.getQuantity(), dto.getUnitPrice(),dto.getTotalPrice(),dto.getFirstSeller().getNickname(),dto.getBuyer().getNickname(),
                dto.getCreatedAt(),dto.getStatus().getBrief(),dto.getReceiverName(),dto.getReceiverAddress(),dto.getReceiverPhone(),dto.getDeliveryNo()
        );

        byte[] content = orderDTOExcelExporter.exportToExcel(dtos, rowMapper);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");
        String fileName = "@%sTO%s.xlsx".formatted(formatter.format(range.getStart()), formatter.format(range.getEnd()));

        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="+fileName);
        headers.add(HttpHeaders.CONTENT_TYPE, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");


        return new ResponseEntity<>(content, headers, HttpStatus.OK);
    }

    @Data
    public static class MakeOrderParam{
        private String productId;
        private int quantity;
        private String recipientId;
        private String remark;
    }

}
